﻿using CPPEI.Coolzon.Common;
using CPPEI.Coolzon.UI.Views;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace CPPEI.Coolzon.Designer.Views
{
    public partial class DesignView
    {
        private Point _layoutPtInCanvasDown;
        private Point _layoutPtInCanvasUp;
        /// <summary>
        /// 放置控件时使用
        /// 鼠标位于组件内部的坐标值
        /// </summary>
        private Point _layoutDownPointInPartContainer;
        /// <summary>
        /// 放置控件时使用
        /// 鼠标位于组件内部的坐标值
        /// </summary>
        private Point _layoutUpPointInPartContainer;


        /// <summary>
        /// 选中的组件实例的值变动
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void _selectedPartInstance_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            //属性变动时,调用Dirtied
            if (Dirtied != null)
            {
                Dirtied();
            }
            // 当时位置属性变动时，更新设计边框的显示
            if (string.Equals(e.PropertyName, "XHeight", StringComparison.CurrentCultureIgnoreCase)
                || string.Equals(e.PropertyName, "XWidth", StringComparison.CurrentCultureIgnoreCase)
                || string.Equals(e.PropertyName, "XTop", StringComparison.CurrentCultureIgnoreCase)
                || string.Equals(e.PropertyName, "XLeft", StringComparison.CurrentCultureIgnoreCase))
            {
                ShowDesignBorder(_selectedPart, this._ctlCanvas);
            }
        }

        /// <summary>
        /// 鼠标在设计场景的canvas上按下
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void _ctlCanvas_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            this._isMLBDown = true;

            if (this._ctlMainFrame.CurrentScene == null)
            {
                return;
            }
            #region 获取鼠标信息
            _pointInCanvas = e.GetPosition(this._ctlCanvas);
            _pointInFrame = e.GetPosition(this._ctlMainFrame);
            _pointInScene = e.GetPosition(this._ctlMainFrame.CurrentScene);
            _mpInScene = e.GetPosition(this._ctlMainFrame.CurrentScene);
            _mpInCanvas = e.GetPosition(this._ctlCanvas);
            _mdpInCanvas = _mpInCanvas;

            _ctlDebug.Text = string.Format("canvas:{0},{1}  frame:{2},{3}  scene:{4},{5}",
                _pointInCanvas.Value.X,
                _pointInCanvas.Value.Y,
                _pointInFrame.Value.X,
                _pointInFrame.Value.Y,
                _pointInScene.Value.X,
                _pointInScene.Value.Y);
            #endregion

            _mdpInScene = _mpInScene;

            //预先检测的移动命中结果，当命中了移动结果
            DesignBorderHitResult resizeHitResult = null;

            #region 现在有选中的组件，如果点击到了选中组件的大小移动点，则进入调整组件大小的模式，否则判断是否选中了其他组件
            //现在有选中的组件，如果点击到了选中组件的大小移动点，则进入调整组件大小的模式，否则判断是否选中了其他组件
            //如果命中的是组件移动点的信息，那么先不进入移动模式，先检测是否有选中的其他对象，如果没有则进入移动模式
            if (this._selectedPart != null)
            {
                // 判断是否点中了移动组件大小的标记点
                DesignBorderHitResult result = _ctlDesignBorder.HitDesignBorderTest(_pointInCanvas.Value, this._ctlCanvas);
                if (this._isEditable && result != null)
                {
                    if (result.Direction == CPPEI.Coolzon.Designer.Views.ResizeDirection.Center)
                    {
                        // 移动方向是中间，先不进入移动模式，如果本次点击没有选中别的元素那么就进入移动模式
                        resizeHitResult = result;
                    }
                    else
                    {
                        #region 选中了设计边框
                        //保存鼠标点击的位置
                        //保存设计边框的当前位置大小信息
                        _dbPosStore = this._ctlDesignBorder.GetOffset();
                        _dbSizeStore = this._ctlDesignBorder.GetSize();

                        _designBorderHitResult = result;

                        //拖动组件的位置或者改变组件大小模式
                        _designData.UpdateState(DesignState.ResizePart);

                        #region 根据_designBorderHitResult.Direction来设计鼠标样式
                        Cursor = Cursors.SizeNESW;
                        #endregion

                        #endregion
                        return;
                    }
                }
            }
            #endregion

            if (_designData.DesignState == DesignState.Normal)
            {
                #region 普通模式，检测命中了哪一个组件
                // 判断是否选中了组件
                CPPEI.Coolzon.UI.Data.XHitResult hitResult = _ctlMainFrame.CurrentScene.XHitTest(_pointInScene.Value);

                if (hitResult.IsSuccess)
                {
                    if (CPPEI.Coolzon.Designer.Views.Util.ValidateUtil.ValidateCanSeleted(hitResult.Part))
                    {
                        //如果当前命中的元素和已经选中的不是一个元素，那么改变选中的组件
                        //如果当前命中的和选中的是一个应该进入移动模式
                        if (this._selectedPart != hitResult.Part)
                        {
                            //命中了不同的组件
                            //取消预先保存的移动测试结果
                            resizeHitResult = null;
                            if (this.SelectedChanged != null)
                            {
                                this.SelectedChanged(hitResult.Part);
                            }
                        }
                        this._selectedPart = hitResult.Part;
                    }
                }
                else
                {
                    this._selectedPart = null;
                }

                if (this._selectedPart != null)
                {
                    //更新mask的位置
                    ShowDesignBorder(_selectedPart, _ctlCanvas);

                    //保存设计边框的当前位置大小信息
                    this._dbPosStore = this._ctlDesignBorder.GetOffset();
                    this._dbSizeStore = this._ctlDesignBorder.GetSize();
                }
                #endregion
            }
            else if (_designData.DesignState == DesignState.DrawPart)
            {
                #region 放置组件
                CPPEI.Coolzon.UI.Data.XHitResult hitResult = _ctlMainFrame.CurrentScene.XHitTest<CPPEI.Coolzon.UI.IPartContainer>(_mdpInScene);

                if (hitResult.IsSuccess)
                {
                    _layoutPartContainer = hitResult.Part as CPPEI.Coolzon.UI.IPartContainer;
                }
                else
                {
                    _layoutPartContainer = null;
                    API_DrawPart(null);
                    return;
                }

                if (!CPPEI.Coolzon.Designer.Views.Util.ValidateUtil.ValidateChildForParent(this._layoutPartContainer, SelectedPartLibItem.Name))
                {
                    // 类型不合适
                    _layoutPartContainer = null;
                    API_DrawPart(null);
                    return;
                }

                // 获取在容器里的点
                _mdpInContainer = DesignUIUtil.PointInCanvasToPartContainer(this._mdpInCanvas,
                    this._ctlCanvas,
                    this._layoutPartContainer);
                // 显示蒙版矩形
                _ctlPreviewRect.Visibility = System.Windows.Visibility.Visible;
                //设置
                CPPEI.Coolzon.Designer.Views.Util.MaskRectUtil.SetPosition(this._ctlPreviewRect,
                    this._mdpInCanvas,
                    this._mdpInCanvas);

                #endregion
            }

            if (this._isEditable && resizeHitResult != null
                && this._selectedPart != null
                && CPPEI.Coolzon.Designer.Views.Util.ValidateUtil.ValidateCanMove(this._selectedPart))
            {
                //保存鼠标点击的位置
                //保存设计边框的当前位置大小信息
                _dbPosStore = this._ctlDesignBorder.GetOffset();
                _dbSizeStore = this._ctlDesignBorder.GetSize();

                _designBorderHitResult = resizeHitResult;

                //拖动组件的位置或者改变组件大小模式
                _designData.UpdateState(DesignState.ResizePart);
                Cursor = Cursors.SizeNESW;
            }
        }
        /// <summary>
        /// 鼠标在canvas上移动
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void _ctlCanvas_PreviewMouseMove(object sender, MouseEventArgs e)
        {
            #region 获取鼠标信息
            _pointInCanvas = e.GetPosition(this._ctlCanvas);
            _pointInFrame = e.GetPosition(this._ctlMainFrame);

            if (this._ctlMainFrame.CurrentScene != null)
            {
                _pointInScene = e.GetPosition(this._ctlMainFrame.CurrentScene);
            }
            else
            {
                _pointInScene = null;
            }

            if (_pointInScene != null)
            {
                _pointInPartContainer = DesignUIUtil.PointInCanvasToPartContainer(_pointInCanvas.Value, _ctlCanvas, _ctlMainFrame.CurrentScene);
                if (_selectedPart != null)
                {
                    _ctlDebug.Text = string.Format("canvas:{0},{1}  frame:{2},{3}  scene:{4},{5}  part:{6} partContainer:{7},{8}",
                        _pointInCanvas.Value.X,
                        _pointInCanvas.Value.Y,
                        _pointInFrame.Value.X,
                        _pointInFrame.Value.Y,
                        _pointInScene.Value.X,
                        _pointInScene.Value.Y,
                        _selectedPart.Name, _pointInPartContainer.Value.X, _pointInPartContainer.Value.Y);
                }
                else
                {
                    _ctlDebug.Text = string.Format("canvas:{0},{1}  frame:{2},{3}  scene:{4},{5} partContainer:{6},{7}",
                        _pointInCanvas.Value.X,
                        _pointInCanvas.Value.Y,
                        _pointInFrame.Value.X,
                        _pointInFrame.Value.Y,
                        _pointInScene.Value.X,
                        _pointInScene.Value.Y, _pointInPartContainer.Value.X, _pointInPartContainer.Value.Y);
                }
            }
            else
            {
                _ctlDebug.Text = string.Format("canvas:{0},{1}  frame:{2},{3}",
                    _pointInCanvas.Value.X,
                    _pointInCanvas.Value.Y,
                    _pointInFrame.Value.X,
                    _pointInFrame.Value.Y);
            }
            #endregion

            Point pointInCanvas = e.GetPosition(this._ctlCanvas);
            this._mpInCanvas = e.GetPosition(this._ctlCanvas);

            if (this._isMLBDown)
            {
                #region 鼠标已处于按下状态
                _mpInScene = e.GetPosition(this._ctlMainFrame.CurrentScene);
                if (_designData.DesignState == DesignState.Normal)
                {
                }

                if (_designData.DesignState == DesignState.ResizePart)
                {
                    double deltaX = (this._mpInScene.X - this._mdpInScene.X) * _ctlMainFrame.ZoomFactor;
                    double deltaY = (this._mpInScene.Y - this._mdpInScene.Y) * _ctlMainFrame.ZoomFactor;
                    ResizePart(_designBorderHitResult.Direction, deltaX, deltaY);
                    ShowGridAlignLineAndMoveDesignBorderTo(_designBorderHitResult.Direction, _selectedPart);
                }
                else if (_designData.DesignState == DesignState.DrawPart)
                {
                    #region
                    // 获取在容器里的点
                    _mpInContainer = e.GetPosition(this._layoutPartContainer as UIElement);
                    //设置
                    CPPEI.Coolzon.Designer.Views.Util.MaskRectUtil.SetPosition(this._ctlPreviewRect,
                        this._mdpInCanvas,
                        this._mpInCanvas);
                    #endregion
                }
                #endregion
            }
            else
            {
                if (_designData.DesignState == DesignState.DrawPart)
                {
                    // 获取鼠标当前所在位置的容器组件
                    CPPEI.Coolzon.UI.Data.XHitResult hitResult = _ctlMainFrame.CurrentScene.XHitTest<CPPEI.Coolzon.UI.IPartContainer>(DesignUIUtil.PointInCanvasToPartContainer(_mpInCanvas, _ctlCanvas, _ctlMainFrame.CurrentScene));

                    if (hitResult.IsSuccess)
                    {
                        //Logger.DebugToTag(Library.LogTAG, string.Format("显示组建:{0}的高亮框", hitResult.Part.Name));
                        _ShowHLBorder4Part(hitResult.Part);
                    }
                    else
                    {
                        Logger.DebugToTag(Library.LogTAG, "关闭高亮框");
                        _ShowHLBorder4Part(null);
                    }
                }
            }
        }
        /// <summary>
        /// 鼠标抬起事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void _ctlCanvas_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            this._isMLBDown = false;
            
            HideGridAlignLine();

            // 关闭大小显示标签
            this.HidePartSizeLabel();

            if (_designData.DesignState == DesignState.ResizePart)
            {
                _designData.UpdateState(DesignState.Normal);
                Point pos = this._selectedPart.XGetPos();
                Size size = this._selectedPart.XGetSize();

                Point curPosOfDB = this._ctlDesignBorder.GetOffset();
                Size curSizeOfDB = this._ctlDesignBorder.GetSize();

                double newLeft = pos.X + (curPosOfDB.X - this._dbPosStore.X) / _ctlMainFrame.ZoomFactor;
                double newTop = pos.Y + (curPosOfDB.Y - this._dbPosStore.Y) / _ctlMainFrame.ZoomFactor;
                double newWidth = size.Width + (curSizeOfDB.Width - this._dbSizeStore.Width) / _ctlMainFrame.ZoomFactor;
                double newHeight = size.Height + (curSizeOfDB.Height - this._dbSizeStore.Height) / _ctlMainFrame.ZoomFactor;

                if (_selectedPart is Coolzon.UI.AreaPart && _selectedPart.ParentPart is Coolzon.UI.ScenePart && (_selectedPart.ParentPart as Coolzon.UI.ScenePart).SceneMatadata.IsAllowSwapArea)
                {
                    double oldLeft = _selectedPart.XLeft;
                    double oldWidth = _selectedPart.XWidth;
                    AreasInSceneResizeOperation operation = new AreasInSceneResizeOperation(this, _selectedPart.ParentPart as Coolzon.UI.ScenePart, _selectedPart as Coolzon.UI.AreaPart, newLeft, newWidth);
                    OperationCenter.Instance.Do(operation);
                    //刷新边框
                    ShowDesignBorder(_selectedPart, this._ctlCanvas);
                }
                else
                {
                    ResizeOperation operation = new ResizeOperation(this, _selectedPart, newLeft, newTop, newWidth, newHeight);
                    OperationCenter.Instance.Do(operation);
                }
            }
            else if (_designData.DesignState == DesignState.DrawPart)
            {
                this._ctlDesignLayoutPartSize.Visibility = System.Windows.Visibility.Hidden;
                #region 放置组件
                this._ctlPreviewRect.Visibility = System.Windows.Visibility.Hidden;

                Coolzon.UI.Part newPart = PartInstanceCache.GetPartInstance(SelectedPartLibItem);

                newPart.Name = GetPartId();
                newPart.XFullName = newPart.Name;
                newPart.XCaption = newPart.Name;
                
                Point mdpInContainer = DesignUIUtil.PointInCanvasToPartContainer(e.GetPosition(this._ctlCanvas),
                    this._ctlCanvas,
                    this._layoutPartContainer);

                Point newPartPoint = new Point();
                newPartPoint.X = Math.Min(this._mdpInContainer.X, mdpInContainer.X);
                newPartPoint.Y = Math.Min(this._mdpInContainer.Y, mdpInContainer.Y);
                Size newPartSize = new Size();
                newPartSize.Width = this._ctlPreviewRect.Width / _ctlMainFrame.ZoomFactor;
                newPartSize.Height = this._ctlPreviewRect.Height / _ctlMainFrame.ZoomFactor;
                AddPartOperation addPartCommand = new AddPartOperation(this, newPart, _layoutPartContainer, newPartPoint, newPartSize, SelectedPartLibItem.Name);
                OperationCenter.Instance.Do(addPartCommand);
                #endregion
            }
        }
        /// <summary>
        /// 鼠标移动出canvas后执行鼠标抬起操作
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _ctlCanvas_MouseLeave(object sender, MouseEventArgs e)
        {
            if (_isMLBDown)
            {
                _ctlCanvas_PreviewMouseLeftButtonUp(sender, new MouseButtonEventArgs(e.MouseDevice, e.Timestamp, MouseButton.Left));
            }
        }
        /// <summary>
        /// 鼠标滚轮事件用于缩放
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void _ctlCanvas_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
        {
            if (Keyboard.IsKeyDown(Key.LeftCtrl)
                || Keyboard.IsKeyDown(Key.RightCtrl))
            {
                if (e.Delta > 0)
                {
                    this._ctlMainFrame.API_Zoom(this._ctlMainFrame.ZoomFactor + 0.1d, e.GetPosition(this._ctlMainFrame));
                }
                else
                {
                    this._ctlMainFrame.API_Zoom(this._ctlMainFrame.ZoomFactor - 0.1d, e.GetPosition(this._ctlMainFrame));
                }
            }
        }
    }
}
